package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
)

//学生成绩管理系统（结构体版本）
package main

import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"os"
)

// 学生类
type Student struct {
	Sid   int
	Name  string
	Score map[string]float64
}

// 学生类的构造函数
func NewStudent(sid int, name string, score map[string]float64) Student {
	return Student{
		Sid:   sid,
		Name:  name,
		Score: score,
	}
}

// 学生管理类
type StuScoreManager struct {
	stus map[int]Student
}

// 学生管理类的构造函数
func NewStuScoreManager() *StuScoreManager {
	return &StuScoreManager{
		stus: make(map[int]Student),
	}
}

// 添加学生成绩
func (ssm StuScoreManager) addScore() {
	// 输入学号和姓名
	var sid int
	var name string
	fmt.Println("请分别输入学号,姓名，以空格隔开.如:1001 yuan")
	fmt.Scan(&sid, &name)

	_, isExist := ssm.stus[sid]
	if isExist {
		fmt.Println("该学生已经存在！")
	} else {
		// 输入成绩
		var chinese, math, english float64
		fmt.Println("请分别输入语数英成绩,以空格隔开.如:100 90 80")
		fmt.Scan(&chinese, &math, &english)
		// fmt.Println(chinese, math, english)

		// 添加学生到data中
		ssm.stus[sid] = NewStudent(sid, name, map[string]float64{
			"chinese": chinese,
			"math":    math,
			"english": english,
		})
		fmt.Println("添加成功")
	}
}

// 查看学生成绩
func (ssm StuScoreManager) checkScore() {
	fmt.Println("------------------------------------------------------------------------------------")
	for _, stu := range ssm.stus {
		fmt.Printf("学号：%-8d 姓名：%-8s 语文成绩：%-8.2f 数学成绩：%-8.2f 英语成绩：%-8.2f",
			stu.Sid, stu.Name, stu.Score["chinese"], stu.Score["math"], stu.Score["english"])
		fmt.Println()
	}
	fmt.Println("------------------------------------------------------------------------------------")
}

// 更新学生成绩
func (ssm StuScoreManager) updateScore() {
	var updateSid int
	fmt.Println("请输入更新学生成绩学号")
	fmt.Scan(&updateSid)
	updateStu, isExist := ssm.stus[updateSid]
	if isExist {
		// 输入成绩
		var chinese, math, english float64
		fmt.Println("请分别输入语数英成绩,以空格隔开.如:100 90 80")
		fmt.Scan(&chinese, &math, &english)
		// 更新data中的学生
		updateStu.Score["chinese"] = chinese
		updateStu.Score["math"] = math
		updateStu.Score["english"] = english
		fmt.Println("更新成功!")
	} else {
		fmt.Println("不存在该学生!")
	}
}

// 删除学生成绩
func (ssm StuScoreManager) deleteScore() {
	var delSid int
	fmt.Println("请输入删除学生成绩学号")
	fmt.Scan(&delSid)
	delete(ssm.stus, delSid)
	fmt.Println("删除成功！")
}

// 获取成绩
func (ssm StuScoreManager) getScore() map[int]Student {

	// 读文件
	content, err := ioutil.ReadFile("score.json")
	if err != nil {
		return nil
	}
	// 反序列化
	data := make(map[int]Student)
	json.Unmarshal(content, &data) // 也可以直接写进ssm.stus中：json.Unmarshal(content, &ssm.stus)
	return data

}

// 保存成绩
func (ssm StuScoreManager) keepScore() {

	// json序列化
	jsonData, _ := json.Marshal(ssm.stus)
	// 写文件
	err := ioutil.WriteFile("score.json", []byte(jsonData), 0666)
	if err != nil {
		fmt.Println("write file failed, err:", err)
		return
	}
	fmt.Println("保存成绩成功！")

}

func showMenu() {
	fmt.Print(`
                        **************************************
                        *  1 添加学生成绩  
                        *  2 查看学生成绩  
                        *  3 更新学生成绩  
                        *  4 删除学生成绩
                        *  5 保存
                        *  6 退出程序    
                        **************************************
`)
}

func main() {

	ssm := NewStuScoreManager()
	ret := ssm.getScore()
	if ret != nil {
		ssm.stus = ret
	}

	for true {
		// 展示菜单
		showMenu()
		// 引导用户做出选择
		var choice int
		fmt.Print("请输入选择:")
		stdin := bufio.NewReader(os.Stdin)
		fmt.Fscan(stdin, &choice)

		switch choice {
		case 1:
			ssm.addScore()
		case 2:
			ssm.checkScore()
		case 3:
			ssm.updateScore()
		case 4:
			ssm.deleteScore()
		case 5:
			ssm.keepScore()
		case 6:
			os.Exit(0)
		default:
			fmt.Println("非法输入！")
		}
	}

}